package at.tugraz.hidipic.web;

import at.tugraz.hidipic.model.*;
import at.tugraz.hidipic.service.DataAccessService;
import at.tugraz.hidipic.upload.UploadService;
import at.tugraz.hidipic.upload.dto.FileUploadDTO;
import at.tugraz.hidipic.web.bean.UserFormBean;
import at.tugraz.hidipic.web.validation.UserFormBeanValidator;
import java.io.*;
import java.net.URL;
import java.util.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import org.apache.log4j.Logger;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.http.converter.AbstractHttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.security.authentication.encoding.Md5PasswordEncoder;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.support.DefaultMultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.support.RequestContextUtils;

@Controller
public class PageController {

    @Value("${upload.path}")
    private String upPath;
    private final Logger LOG = Logger.getLogger(PageController.class);
    @Autowired
    private HibernateTemplate hibernateTemplate;
    @Autowired
    private UploadService uploadService;
    @Autowired
    DataAccessService dataAccessService;
    @Autowired
    UserFormBeanValidator userFormBeanValidator;

    /**
     * login view
     *
     * @return the model and view
     */
    @RequestMapping(value = "/login")
    public ModelAndView login() {
        ModelAndView mav = new ModelAndView("login");
        return mav;
    }

    /**
     * access denied view
     *
     * @return the model and view
     */
    @RequestMapping(value = "/accessdenied")
    public ModelAndView accessdenied() {
        ModelAndView mav = new ModelAndView("accessdenied");
        return mav;
    }

    /**
     * help view
     *
     * @return the model and view
     */
    @RequestMapping(value = "/help")
    public ModelAndView help() {
        ModelAndView mav = new ModelAndView("help");
        return mav;
    }

    /**
     * create view
     *
     * @return the model and view
     */
    @RequestMapping(value = "/create", method = RequestMethod.GET)
    public ModelAndView create() {
        ModelAndView mav = new ModelAndView("creates1");
        User loggedIn = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        User user = hibernateTemplate.get(User.class, loggedIn.getUsername());
        List<SubProject> subProjects = dataAccessService.getResearcherSubProjectsForUser(user);
        List<Project> projects = new ArrayList<Project>();
        for (SubProject sp : subProjects) {
            if (!projects.contains(sp.getParent())) {
                projects.add(sp.getParent());
            }
        }
        mav.addObject("projects", projects);
        return mav;
    }

    /**
     * create view for the project stage
     *
     * @return the model and view
     */
    @RequestMapping(value = "/create/project/{projectId}", method = RequestMethod.GET)
    public ModelAndView create(@PathVariable("projectId") String projectId) {
        ModelAndView mav = new ModelAndView("creates2");
        int pid = -1;
        try {
            pid = Integer.parseInt(projectId);
        } catch (Exception e) {
            LOG.error(e);
        }
        User loggedIn = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        User user = hibernateTemplate.get(User.class, loggedIn.getUsername());
        Project project = hibernateTemplate.get(Project.class, pid);
        if (!dataAccessService.isProjectAvailableToUser(project, user)) {
            return accessdenied();
        }
        List<SubProject> subProjects = dataAccessService.getResearcherSubProjectsForUserInProject(user, project);
        mav.addObject("projectId", projectId);
        mav.addObject("methods", project.getMethods());
        mav.addObject("subProjects", subProjects);
        return mav;
    }

    /**
     * result detail view
     *
     * @return the model and view
     */
    @RequestMapping(value = "/result/{resultId}", method = RequestMethod.GET)
    public ModelAndView showResult(@PathVariable("resultId") String resultId, HttpServletRequest request) {
        ModelAndView mav = null;
        int pid = -1;
        try {
            pid = Integer.parseInt(resultId);
        } catch (Exception e) {
            LOG.error(e);
        }
        if (pid >= 0) {
            User loggedIn = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
            User user = hibernateTemplate.get(User.class, loggedIn.getUsername());
            Result result = hibernateTemplate.get(Result.class, pid);
            if (!dataAccessService.isSubProjectAvailableToUser(result.getSubProject(), user)) {
                return accessdenied();
            }
            List<Comment> comments = new ArrayList<Comment>(dataAccessService.getCommentsForResult(result));
            Collections.sort(comments, new Comparator<Comment>() {

                @Override
                public int compare(Comment o1, Comment o2) {
                    return o1.getCreationDate().compareTo(o2.getCreationDate());
                }
            });
            List<DataItem> dis = new ArrayList<DataItem>(result.getInputData());
            Collections.sort(dis, new Comparator<DataItem>() {

                @Override
                public int compare(DataItem o1, DataItem o2) {
                    return o1.getCreated().compareTo(o2.getCreated());
                }
            });
            List<DataItem> dos = new ArrayList<DataItem>(dataAccessService.getOutputDataForResult(result));
            Collections.sort(dos, new Comparator<DataItem>() {

                @Override
                public int compare(DataItem o1, DataItem o2) {
                    return o1.getCreated().compareTo(o2.getCreated());
                }
            });
            Method method = result.getMethod();
            String methodName = method.getName();
            mav = new ModelAndView("result");
            mav.addObject("methodName", methodName);
            mav.addObject("customInclude", "customresult/" + methodName + ".jsp");
            mav.addObject("outputData", dos);
            mav.addObject("uploadedData", dis);
            Comment comment = new Comment();
            mav.addObject("projectComment", comment);
            mav.addObject("comments", comments);
            mav.addObject("result", result);
            return mav;
        }
        return accessdenied();
    }

    @RequestMapping(value = "/allresults", method = RequestMethod.GET)
    public ModelAndView showAllResultsForUser() {
        ModelAndView mav = new ModelAndView("results");
        User loggedIn = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        User user = hibernateTemplate.get(User.class, loggedIn.getUsername());
        List<Result> createdResults = dataAccessService.getCreatedResultsForUser(user, null);
        mav.addObject("lastResults", createdResults);
        return mav;
    }

    /**
     * manage view for researchers
     *
     * @return the model and view
     */
    @RequestMapping(value = "/manage", method = RequestMethod.GET)
    public ModelAndView manage() {
        ModelAndView mav = new ModelAndView("manage");
        User loggedIn = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        User user = hibernateTemplate.get(User.class, loggedIn.getUsername());
        List<Project> leadProjects = dataAccessService.getLeadProjectsForUser(user);
        List<SubProject> researcherProjects = dataAccessService.getResearcherSubProjectsForUser(user);
        List<DataItem> dis = new ArrayList<DataItem>(dataAccessService.getCreatedDataForUser(user));
        Collections.sort(dis, new Comparator<DataItem>() {

            @Override
            public int compare(DataItem o1, DataItem o2) {
                return o1.getCreated().compareTo(o2.getCreated());
            }
        });
        for (Project p : leadProjects) {
            p.setSubProjects(dataAccessService.getSubProjectsForProject(p));
        }
        List<Result> createdResults = dataAccessService.getCreatedResultsForUser(user, 10);
        mav.addObject("lastResults", createdResults);
        mav.addObject("uploadedData", dis);
        mav.addObject("leadProjects", leadProjects);
        mav.addObject("researcherProjects", researcherProjects);
        mav.addObject("user", user);
        return mav;
    }

    /**
     * events view for followed subprojects
     *
     * @return the model and view
     */
    @RequestMapping(value = "/events", method = RequestMethod.GET)
    public ModelAndView showEvents() {
        ModelAndView mav = new ModelAndView("events");
        User loggedIn = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        User user = hibernateTemplate.get(User.class, loggedIn.getUsername());
        List<Event> events = dataAccessService.getEventsForUser(user, null);
        mav.addObject("events", events);
        return mav;
    }

    /**
     * events view for subproject
     *
     * @return the model and view
     */
    @RequestMapping(value = "/events/subproject/{subProjectId}", method = RequestMethod.GET)
    public ModelAndView showEventsSubProject(@PathVariable("subProjectId") String subProjectId) {
        int pid = -1;
        try {
            pid = Integer.parseInt(subProjectId);
        } catch (Exception e) {
            LOG.error(e);
        }
        if (pid >= 0) {
            ModelAndView mav = new ModelAndView("events");
            User loggedIn = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
            User user = hibernateTemplate.get(User.class, loggedIn.getUsername());
            SubProject sp = hibernateTemplate.get(SubProject.class, pid);
            if (!dataAccessService.isSubProjectAvailableToUser(sp, user)) {
                return accessdenied();
            }
            List<Event> events = dataAccessService.getEventsForSubProject(sp, null);
            mav.addObject("events", events);
            return mav;
        }
        return handleRequest();
    }

    /**
     * home view with events, statistics and followed subprojects
     *
     * @return the model and view
     */
    @RequestMapping(value = "/*", method = RequestMethod.GET)
    public ModelAndView handleRequest() {
        User loggedIn = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        User user = hibernateTemplate.get(User.class, loggedIn.getUsername());
        ModelAndView mav = new ModelAndView("home");
        List<Project> projs = hibernateTemplate.find("from Project");
        mav.addObject("projs", projs);
        List<Event> events = dataAccessService.getEventsForUser(user, 10);
        Map<String, Integer> stats = dataAccessService.getStatistics();
        List<SubProject> followedProjects = dataAccessService.getFollowedSubProjectsForUser(user);
        Collections.sort(followedProjects, new Comparator<SubProject>() {

            @Override
            public int compare(SubProject o1, SubProject o2) {
                Integer into1 = o1.getParent().getId();
                Integer into2 = o2.getParent().getId();
                return into1.compareTo(into2);
            }
        });
        mav.addObject("followProjects", followedProjects);
        mav.addObject("events", events);
        mav.addObject("projects", stats.get("projects"));
        mav.addObject("users", stats.get("users"));
        mav.addObject("subprojects", stats.get("subprojects"));
        mav.addObject("methods", stats.get("methods"));
        mav.addObject("results", stats.get("results"));
        mav.addObject("comments", stats.get("comments"));
        mav.addObject("eventstat", stats.get("events"));
        mav.addObject("data", stats.get("data"));
        return mav;
    }

    /**
     * subproject detailview
     *
     * @return the model and view
     */
    @RequestMapping(value = "subproject/{projectId}", method = RequestMethod.GET)
    public ModelAndView showSubProductDetail(@PathVariable("projectId") String projectId) {
        ModelAndView mav = new ModelAndView("subproject");
        User loggedIn = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        User user = hibernateTemplate.get(User.class, loggedIn.getUsername());
        int pid = -1;
        try {
            pid = Integer.parseInt(projectId);
        } catch (Exception e) {
            LOG.error(e);
        }
        if (pid >= 0) {
            SubProject project = hibernateTemplate.get(SubProject.class, pid);
            if (project != null) {
                if (!dataAccessService.isSubProjectAvailableToUser(project, user)) {
                    return accessdenied();
                }
                mav.addObject("project", project);
                List<Comment> comments = dataAccessService.getCommentsForSubProject(project);
                Collections.sort(comments, new Comparator<Comment>() {

                    @Override
                    public int compare(Comment o1, Comment o2) {
                        return o1.getCreationDate().compareTo(o2.getCreationDate());
                    }
                });
                List<Result> results = dataAccessService.getResultsForSubProject(project);
                Collections.sort(results, new Comparator<Result>() {

                    @Override
                    public int compare(Result o1, Result o2) {
                        return o1.getCreationDate().compareTo(o2.getCreationDate());
                    }
                });
                List<User> users = hibernateTemplate.find("from User ORDER BY username ASC");
                List<String> userList = new ArrayList<String>();
                for (User u : users) {
                    userList.add(u.getUsername());
                }
                List<Event> events = dataAccessService.getEventsForSubProject(project, 10);
                Project p = project.getParent();
                if (user.getUsername().equals(p.getProjectLeader().getUsername())) {
                    mav.addObject("isLeader", true);
                }
                mav.addObject("events", events);
                mav.addObject("users", userList);
                mav.addObject("results", results);
                mav.addObject("comments", comments);
                Comment comment = new Comment();
                mav.addObject("projectComment", comment);
            }
        }
        return mav;
    }

    /**
     * detailview for project
     *
     * @return the model and view
     */
    @RequestMapping(value = "project/{projectId}", method = RequestMethod.GET)
    public ModelAndView showProjectDetail(@PathVariable("projectId") String projectId) {
        ModelAndView mav = new ModelAndView("project");
        int pid = -1;
        try {
            pid = Integer.parseInt(projectId);
        } catch (Exception e) {
            LOG.error(e);
        }
        if (pid >= 0) {
            User loggedIn = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
            User user = hibernateTemplate.get(User.class, loggedIn.getUsername());
            Project project = hibernateTemplate.get(Project.class, pid);
            if (project != null) {
                if (!dataAccessService.isProjectAvailableToUser(project, user)) {
                    return accessdenied();
                }
                mav.addObject("project", project);
                List<Comment> comments = dataAccessService.getCommentsForProject(project);
                Collections.sort(comments, new Comparator<Comment>() {

                    @Override
                    public int compare(Comment o1, Comment o2) {
                        return o1.getCreationDate().compareTo(o2.getCreationDate());
                    }
                });
                Set<SubProject> subProjects = dataAccessService.getSubProjectsForProject(project);
                mav.addObject("subProjects", subProjects);
                mav.addObject("comments", comments);
                Comment comment = new Comment();
                mav.addObject("projectComment", comment);
                return mav;
            }
        }
        return handleRequest();
    }

    /**
     * overview for upload
     *
     * @return the model and view
     */
    @RequestMapping(value = "/upload", method = RequestMethod.GET)
    public ModelAndView uploadFile() {
        ModelAndView mav = new ModelAndView("upload");
        return mav;
    }

    /**
     * uploading-posttarget
     *
     * @param multipartRequest
     * @param response
     * @throws IOException
     */
    @RequestMapping(value = "/upload", method = RequestMethod.POST)
    public void doUpload(DefaultMultipartHttpServletRequest multipartRequest, HttpServletResponse response) throws IOException {
        if (multipartRequest != null) {
            User loggedIn = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
            User user = hibernateTemplate.get(User.class, loggedIn.getUsername());
            List<String> requestParameterNames = Collections.list((Enumeration<String>) multipartRequest.getParameterNames());
            String[] titleList = multipartRequest.getParameterValues("title[]");
            Iterator iterator = multipartRequest.getFileNames();
            List<FileUploadDTO> dtoList = new ArrayList<FileUploadDTO>();
            int i = 0;

            while (iterator.hasNext()) {
                String fileName = null;
                if (i < titleList.length) {
                    fileName = titleList[i];
                }
                FileUploadDTO dto = new FileUploadDTO();
                MultipartFile multifile = multipartRequest.getFile((String) iterator.next());
                String uploadPath = upPath; //"d:/dl/tmppic/";
                if (StringUtils.hasText(multifile.getOriginalFilename())) {
                    String type = null;
                    String extension = null;
                    if (multifile.getOriginalFilename().length() > 3) {
                        int dotPos = multifile.getOriginalFilename().lastIndexOf(".");
                        extension = multifile.getOriginalFilename().substring(dotPos + 1);
                        if (extension.equals("csv")) {
                            type = KDDConstants.DATA_ITEM_TYPE_CSV;
                        } else if (extension.equals("png") || extension.equals("jpg") || extension.equals("gif")) {
                            type = KDDConstants.DATA_ITEM_TYPE_IMG;
                        } else {
                            type = KDDConstants.DATA_ITEM_TYPE_TXT;
                        }
                    }
                    String path = uploadService.saveFile(multifile, uploadPath, fileName, user, type, extension);

                    dto.setName(multifile.getOriginalFilename());
                    dto.setSize(multifile.getSize());
                    dto.setUrl(path);
                    dto.setThumbnail_url(path);
                    dto.setDelete_type("DELETE");
                    dto.setDelete_url("");
                    dtoList.add(dto);
                }
                i++;
            }
            ObjectMapper mapper = new ObjectMapper();
            String json = mapper.writeValueAsString(dtoList);
            AbstractHttpMessageConverter<String> converter = new StringHttpMessageConverter();
            MediaType jsonMime = MediaType.APPLICATION_JSON;

            if (converter.canWrite(String.class, jsonMime)) {



                try {
                    converter.write(json, jsonMime, new ServletServerHttpResponse(response));
                } catch (IOException e) {
                    LOG.error("ERROR writing the JSON Response");
                } catch (HttpMessageNotWritableException e) {
                    LOG.error("Can not write JSON Response");
                }
            }
        }
    }

    /**
     * settings overview
     *
     * @return the model and view
     */
    @RequestMapping(value = "/settings", method = RequestMethod.GET)
    public ModelAndView changeSettings() {
        User loggedIn = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        User user = hibernateTemplate.get(User.class, loggedIn.getUsername());
        ModelAndView mav = new ModelAndView("settings");
        UserFormBean ufb = new UserFormBean();
        ufb.setUsername(user.getUsername());
        List<SubProject> sharedProjects = dataAccessService.getSharedSubProjectsForUser(user);
        mav.addObject("sharedSubProjects", sharedProjects);
        mav.addObject("loggedUser", user);
        mav.addObject("user", ufb);
        return mav;
    }

    /**
     * target for following a subproject
     *
     * @param subProjectId
     * @return a redirect to the settings page
     */
    @RequestMapping(value = "/settings/follow/{subProjectId}", method = RequestMethod.GET)
    public String doSubProjectFollowing(@PathVariable("subProjectId") String subProjectId) {
        User loggedIn = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        User user = hibernateTemplate.get(User.class, loggedIn.getUsername());
        List<SubProject> subProjects = dataAccessService.getSharedSubProjectsForUser(user);
        int projectId = -1;
        try {
            projectId = Integer.parseInt(subProjectId);
            SubProject sp = hibernateTemplate.get(SubProject.class, projectId);
            if (subProjects.contains(sp)) {
                Set<SubProject> followList = user.getFollowSubProjects();
                followList.add(sp);
                user.setFollowSubProjects(followList);
                hibernateTemplate.merge(user);
            }
            return "redirect:/settings";
        } catch (Exception e) {
            LOG.error(e);
        }

        return "redirect:/settings";
    }

    /**
     * request for changing the locale
     *
     * @param locale
     * @param request
     * @param response
     * @return redirect to home page
     */
    @RequestMapping(value = "/localechange/{locale}", method = RequestMethod.GET)
    public String changeLocale(@PathVariable("locale") String locale, HttpServletRequest request, HttpServletResponse response) {
        if (locale != null) {
            if (locale.equals("de")) {
                RequestContextUtils.getLocaleResolver(request).setLocale(request, response, Locale.GERMAN);
            } else {
                RequestContextUtils.getLocaleResolver(request).setLocale(request, response, Locale.ENGLISH);
            }
        }
        return "redirect:/home";
    }

    /**
     * target for unfollowing a subproject
     *
     * @param subProjectId
     * @return a redirect to the settings page
     */
    @RequestMapping(value = "/settings/unfollow/{subProjectId}", method = RequestMethod.GET)
    public String doSubProjectUnFollowing(@PathVariable("subProjectId") String subProjectId) {
        User loggedIn = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        User user = hibernateTemplate.get(User.class, loggedIn.getUsername());
        List<SubProject> subProjects = dataAccessService.getSharedSubProjectsForUser(user);
        int projectId = -1;
        try {
            projectId = Integer.parseInt(subProjectId);
            SubProject sp = hibernateTemplate.get(SubProject.class, projectId);
            if (subProjects.contains(sp)) {
                Set<SubProject> followList = user.getFollowSubProjects();
                followList.remove(sp);
                user.setFollowSubProjects(followList);
                hibernateTemplate.merge(user);
            }
            return "redirect:/settings";
        } catch (Exception e) {
            LOG.error(e);
        }

        return "redirect:/settings";
    }

    /**
     * request for passwordchange
     *
     * @param user
     * @param result
     * @return the model and view
     */
    @RequestMapping(value = "/settings", method = RequestMethod.POST)
    public ModelAndView doChangeSettings(@ModelAttribute("user") UserFormBean user, BindingResult result) {
        User loggedIn = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        User u = hibernateTemplate.get(User.class, loggedIn.getUsername());
        if (user
                != null) {
            String pw = user.getPassword();
            user.setUsername(u.getUsername());
            userFormBeanValidator.validate(user, result, true);
            if (!result.hasErrors()) {
                try {
                    if (pw != null && org.apache.commons.lang.StringUtils.isNotEmpty(pw)) {
                        Md5PasswordEncoder md5pe = new Md5PasswordEncoder();
                        u.setPassword(md5pe.encodePassword(pw, null));
                    }
                    hibernateTemplate.merge(u);
                    ModelAndView mav = handleRequest();
                    return mav;
                } catch (Exception e) {
                    LOG.error(e);
                }
            }
        }
        if (result.hasErrors()) {
            ModelAndView mav = changeSettings();
            mav.addObject("user", user);
            return mav;
        }
        ModelAndView mav = handleRequest();
        return mav;
    }

    /**
     * persists a comment with a modifier for the different types
     *
     * @param projectComment
     * @param loggedIn
     * @param id
     * @param type 1: project, 2: subproject, 3: result
     */
    private void persistComment(Comment projectComment, User loggedIn, int id, int type) {
        if (id >= 0 && loggedIn != null && projectComment != null) {
            if (type == 1) {
                Project p = hibernateTemplate.get(Project.class, id);
                if (p != null) {
                    if (dataAccessService.isProjectAvailableToUser(p, loggedIn)) {
                        projectComment.setProject(p);
                        projectComment.setCreationDate(new Date());
                        projectComment.setCreator(loggedIn);
                        hibernateTemplate.save(projectComment);
                    }
                }
            } else if (type == 2) {
                SubProject p = hibernateTemplate.get(SubProject.class, id);
                if (p != null) {
                    if (dataAccessService.isSubProjectAvailableToUser(p, loggedIn)) {
                        projectComment.setSubProject(p);
                        projectComment.setCreationDate(new Date());
                        projectComment.setCreator(loggedIn);
                        hibernateTemplate.save(projectComment);
                    }
                }
            } else if (type == 3) {
                Result p = hibernateTemplate.get(Result.class, id);
                if (p != null) {
                    if (dataAccessService.isSubProjectAvailableToUser(p.getSubProject(), loggedIn)) {
                        projectComment.setResult(p);
                        projectComment.setCreationDate(new Date());
                        projectComment.setCreator(loggedIn);
                        hibernateTemplate.save(projectComment);
                    }
                }
            }
        }
    }

    /**
     * request for adding a comment
     *
     * @param projectId
     * @param projectComment
     * @param result
     * @return redirect to the project page
     */
    @RequestMapping(value = "/comment/project/add/{projectId}", method = RequestMethod.POST)
    public String projectComment(@PathVariable("projectId") String projectId, @ModelAttribute("projectComment")
            @Valid Comment projectComment, BindingResult result) {
        if (!result.hasErrors()) {
            int pid;
            try {
                User loggedIn = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
                User u = hibernateTemplate.get(User.class, loggedIn.getUsername());
                pid = Integer.parseInt(projectId);

                persistComment(projectComment, u, pid,
                        1);
                return "redirect:/project/" + projectId;
            } catch (Exception e) {
                LOG.error(e);
            }
        }
        return "redirect:/project/" + projectId;
    }

    /**
     * request for adding a comment
     *
     * @param projectId
     * @param projectComment
     * @param result
     * @return redirect to the result page
     */
    @RequestMapping(value = "/comment/result/add/{projectId}", method = RequestMethod.POST)
    public String resultComment(@PathVariable("projectId") String projectId, @ModelAttribute("projectComment")
            @Valid Comment projectComment, BindingResult result) {
        if (!result.hasErrors()) {
            int pid;
            try {
                User loggedIn = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
                User u = hibernateTemplate.get(User.class, loggedIn.getUsername());
                pid = Integer.parseInt(projectId);

                persistComment(projectComment, u, pid,
                        3);
                return "redirect:/result/" + projectId;
            } catch (Exception e) {
                LOG.error(e);
            }
        }
        return "redirect:/project/" + projectId;
    }

    /**
     * request for adding a comment
     *
     * @param projectId
     * @param projectComment
     * @param result
     * @return redirect to the subproject page
     */
    @RequestMapping(value = "/comment/subproject/add/{projectId}", method = RequestMethod.POST)
    public String subProjectComment(@PathVariable("projectId") String projectId, @ModelAttribute("projectComment")
            @Valid Comment projectComment, BindingResult result) {
        if (!result.hasErrors()) {
            int pid;
            try {
                User loggedIn = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
                User u = hibernateTemplate.get(User.class, loggedIn.getUsername());
                pid = Integer.parseInt(projectId);

                persistComment(projectComment, u, pid,
                        2);
                return "redirect:/subproject/" + projectId;
            } catch (Exception e) {
                LOG.error(e);
            }
        }
        return "redirect:/subproject/" + projectId;
    }

    /**
     * request for adding a shared user to a subproject
     *
     * @param shareUser
     * @param subProjectId
     * @return redirect to subproject page
     */
    @RequestMapping(value = "/subproject/addSharedUser/{subProjectId}", method = RequestMethod.POST)
    public String subProjectAddSharedUser(@RequestParam("sharedUserAdd") String shareUser, @PathVariable("subProjectId") String subProjectId) {
        User user = hibernateTemplate.get(User.class, shareUser);
        User loggedIn = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        User u = hibernateTemplate.get(User.class, loggedIn.getUsername());
        if (user
                != null) {
            int pid = -1;
            try {
                pid = Integer.parseInt(subProjectId);
            } catch (Exception e) {
                LOG.error(e);
            }
            if (pid >= 0) {
                SubProject subProject = hibernateTemplate.get(SubProject.class, pid);
                if (!dataAccessService.isSubProjectAvailableToUser(subProject, u)) {
                    return "redirect:/accessdenied";
                }
                if (subProject != null) {
                    Set<User> sharedUsers = subProject.getSharedUserList();
                    try {
                        sharedUsers.add(user);
                        subProject.setSharedUserList(sharedUsers);
                        hibernateTemplate.merge(subProject);
                    } catch (Exception e) {
                        LOG.error(e);
                    }
                }
            }
        }
        return "redirect:/subproject/" + subProjectId;
    }

    /**
     * request for removing a shared user from a subproject
     *
     * @param subProjectId
     * @param userId
     * @return redirect to the subproject
     */
    @RequestMapping(value = "/subproject/deleteSharedUser/{subProjectId}/{userId}", method = RequestMethod.GET)
    public String subProjectDeleteSharedUser(@PathVariable("subProjectId") String subProjectId, @PathVariable("userId") String userId) {
        User user = hibernateTemplate.get(User.class, userId);
        User loggedIn = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        User u = hibernateTemplate.get(User.class, loggedIn.getUsername());
        if (user
                != null) {
            int pid = -1;
            try {
                pid = Integer.parseInt(subProjectId);
            } catch (Exception e) {
                LOG.error(e);
            }
            if (pid >= 0) {
                SubProject subProject = hibernateTemplate.get(SubProject.class, pid);
                if (!dataAccessService.isSubProjectAvailableToUser(subProject, u)) {
                    return "redirect:/accessdenied";
                }
                if (subProject != null) {
                    Set<User> sharedUsers = subProject.getSharedUserList();
                    try {
                        sharedUsers.remove(user);
                        subProject.setSharedUserList(sharedUsers);
                        hibernateTemplate.merge(subProject);
                    } catch (Exception e) {
                        LOG.error(e);
                    }
                }
            }
        }
        return "redirect:/subproject/" + subProjectId;
    }
}
